package com.cskaoyan.javase.oop2.initialization6.explicit3;

/**
 * @description: 显式的子类对象初始化
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 *显式初始化，需要程序员手动写代码，告诉JVM调用哪个父类构造器
 *
 * - 必须在子类构造器的第一行，显式的调用父类构造方法，那么如何调用父类构造器？
 * 通过super关键字，super(参数)的形式调用父类构造方法
 * super(参数)这种形式和this(参数)使用方法一模一样，只不过this是自身构造器
 * super是父类构造器
 *
 * ​	1，无论是隐式还是显式，最终都是为了保证父类构造器先于子类的构造器执行
 * ​	2，若父类中不存在默认构造方法，则必须在子类构造方法中使用super关键字调用父类的其他构造器
 * ​	3，在子类构造方法中，super语句必须在第一行
 * ​	4，在子类构造方法中，也可以用this调用自身构造，也必须在第一行
 * ​	5，this和super不能共存
 * ​	6，构造代码块和静态代码块也是“先父后子”
 *
 * this为什么在第一行，super为什么也在第一行？
 * 它两都想在第一行，能不能共存？所以这两个关键字一定不能共存，一定不可能同时出现在一个构造方法当中
 * 指的是在构造方法中，调用别的构造器的时候，不能共存
 *
 * 解释一下，为啥不能共存，为啥都想争第一行？
 * 	因为子类构造器第一行永远都有一个super()关键字调用，如果你自己的super和this不在第一行，会形成循环调用父类构造器
 *
 */
public class Demo {
    public static void main(String[] args) {
        //创建子类对象，希望直接给父类的name属性赋值
        //这个时候就必须显式的使用super()调用父类的name构造器
        Cat cat = new Cat("大黄");
        System.out.println(cat.name);
    }
}


class Animal {
    String name;

    public Animal(String name) {
        this.name = name;
    }

    public Animal() {

    }
}

class Cat extends Animal {
    public Cat() {
        //其他构造器当中可能还有this
        //成员变量的数量肯定是有限的，构造器的数量也不可能是无限的，也是有限的
        //最终肯定有一个构造器 不能再调用别人了
        //于是第一行默认super()
        //只要你放在后面，就有可能多次调用super()构造器
    }

    public Cat(String name) {
        //这里如果什么都不写，会隐式调用super()
        //但是我们要给name属性赋值，必须调用父类的name构造器
        //'Animal(java.lang.String)' has private access in 'com.cskaoyan.javase.oop2.initialization6.explicit3.Animal'
        //this();
        //System.out.println("112312");
        //
        //super(name);
        //如果允许super()或者this()不在第一行
        //那么第一行一定有一个super()
        //于是第一行的super()去调用了父类的无参构造
        //然后调完了回来了，发现你在后面又写了一个super()，他就无语了，我刚调用了父类构造方法，为啥你后面又来一个
        //如果你第二行以后有一个this，它又去调当前类的其他构造器
    }
}
